home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 388_01 / ae / 91 / winner / aeae.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-19  |  4.9 KB  |  361 lines

  1. /*
  2.  *    ae.c        Anthony's Editor  IOCCC '91
  3.  *
  4.  *    Public Domain 1991 by Anthony Howe.  All rights released.
  5.  */
  6.  
  7. #include <ctype.h>
  8. #include <curses.h>
  9.  
  10. int done;
  11. int row, col;
  12. int index, page, epage;
  13. char buf[BUF];
  14. char *ebuf;
  15. char *gap = buf;
  16. char *egap;
  17. char *filename;
  18.  
  19. /*
  20.  *    The following assertions must be maintained.
  21.  *
  22.  *    o  buf <= gap <= egap <= ebuf
  23.  *        If gap == egap then the buffer is full.
  24.  *
  25.  *    o  point = ptr(index) and point < gap or egap <= point
  26.  *
  27.  *    o  page <= index < epage
  28.  *
  29.  *    o  0 <= index <= pos(ebuf) <= BUF
  30.  *
  31.  *
  32.  *    Memory representation of the file:
  33.  *
  34.  *        low    buf  -->+----------+
  35.  *                |  front   |
  36.  *                | of file  |
  37.  *            gap  -->+----------+<-- character not in file 
  38.  *                |   hole   |
  39.  *            egap -->+----------+<-- character in file
  40.  *                |   back   |
  41.  *                | of file  |
  42.  *        high    ebuf -->+----------+<-- character not in file 
  43.  *
  44.  *
  45.  *    point & gap
  46.  *
  47.  *    The Point is the current cursor position while the Gap is the 
  48.  *    position where the last edit operation took place. The Gap is 
  49.  *    ment to be the cursor but to avoid shuffling characters while 
  50.  *    the cursor moves it is easier to just move a pointer and when 
  51.  *    something serious has to be done then you move the Gap to the 
  52.  *    Point. 
  53.  */
  54.  
  55. int adjust();
  56. int nextline();
  57. int pos();
  58. int prevline();
  59. char *ptr();
  60.  
  61. void bottom();
  62. void delete();
  63. void display();
  64. void down();
  65. void file();
  66. void insert();
  67. void left();
  68. void lnbegin();
  69. void lnend();
  70. void movegap();
  71. void pgdown();
  72. void pgup();
  73. void redraw();
  74. void right();
  75. void quit();
  76. void top();
  77. void up();
  78. void wleft();
  79. void wright();
  80.  
  81. char key[] = "hjklHJKL[]tbixWRQ";
  82. void (*func[])() = {
  83.     left, down, up, right, 
  84.     wleft, pgdown, pgup, wright,
  85.     lnbegin, lnend, top, bottom, 
  86.     insert, delete, file, redraw, quit, movegap
  87. };
  88.  
  89. char *
  90. ptr(offset)
  91. int offset;
  92. {
  93.     if (offset < 0)
  94.         return (buf);
  95.     return (buf+offset + (buf+offset < gap ? 0 : egap-gap));
  96. }
  97.  
  98. int
  99. pos(pointer)
  100. char *pointer;
  101. {
  102.     return (pointer-buf - (pointer < egap ? 0 : egap-gap)); 
  103. }
  104.  
  105. void
  106. top()
  107. {
  108.     index = 0;
  109. }
  110.  
  111. void
  112. bottom()
  113. {
  114.     epage = index = pos(ebuf);
  115. }
  116.  
  117. void
  118. quit()
  119. {
  120.     done = 1;
  121. }
  122.  
  123. void
  124. redraw()
  125. {
  126.     clear();
  127.     display();
  128. }
  129.  
  130. void
  131. movegap()
  132. {
  133.     char *p = ptr(index);
  134.     while (p < gap)
  135.         *--egap = *--gap;
  136.     while (egap < p)
  137.         *gap++ = *egap++;
  138.     index = pos(egap);
  139. }
  140.  
  141. int
  142. prevline(offset)
  143. int offset;
  144. {
  145.     char *p;
  146.     while (buf < (p = ptr(--offset)) && *p != '\n')
  147.         ;
  148.     return (buf < p ? ++offset : 0);
  149. }
  150.  
  151. int
  152. nextline(offset)
  153. int offset;
  154. {
  155.     char *p;
  156.     while ((p = ptr(offset++)) < ebuf && *p != '\n')    
  157.         ;
  158.     return (p < ebuf ? offset : pos(ebuf));
  159. }
  160.  
  161. int
  162. adjust(offset, column)
  163. int offset, column;
  164. {
  165.     char *p;
  166.     int i = 0;
  167.     while ((p = ptr(offset)) < ebuf && *p != '\n' && i < column) {
  168.         i += *p == '\t' ? 8-(i&7) : 1;
  169.         ++offset;
  170.     }
  171.     return (offset);
  172. }
  173.  
  174. void
  175. left()
  176. {
  177.     if (0 < index)
  178.         --index;
  179.  
  180. void
  181. right()
  182. {
  183.     if (index < pos(ebuf))
  184.         ++index;
  185. }
  186.  
  187. void
  188. up()
  189. {
  190.     index = adjust(prevline(prevline(index)-1), col);
  191. }
  192.  
  193. void
  194. down()
  195. {
  196.     index = adjust(nextline(index), col);
  197. }
  198.  
  199. void
  200. lnbegin()
  201. {
  202.     index = prevline(index);
  203. }
  204.  
  205. void
  206. lnend()
  207. {
  208.     index = nextline(index);
  209.     left();
  210. }
  211.  
  212. void
  213. wleft()
  214. {
  215.     char *p;
  216.     while (!isspace(*(p = ptr(index))) && buf < p)
  217.         --index;
  218.     while (isspace(*(p = ptr(index))) && buf < p)
  219.         --index;
  220. }
  221.  
  222. void
  223. pgdown()
  224. {
  225.     page = index = prevline(epage-1);
  226.     while (0 < row--)
  227.         down();
  228.     epage = pos(ebuf);
  229. }
  230.  
  231. void
  232. pgup()
  233. {
  234.     int i = LINES;
  235.     while (0 < --i) {
  236.         page = prevline(page-1); 
  237.         up();
  238.     }
  239. }
  240.  
  241. void
  242. wright()
  243. {
  244.     char *p;
  245.     while (!isspace(*(p = ptr(index))) && p < ebuf)
  246.         ++index;
  247.     while (isspace(*(p = ptr(index))) && p < ebuf)
  248.         ++index;
  249. }
  250.  
  251. void
  252. insert()
  253. {
  254.     int ch;
  255.     movegap();
  256.     while ((ch = getch()) != '\f') {
  257.         if (ch == '\b') {
  258.             if (buf < gap)
  259.                 --gap;
  260.         } else if (gap < egap) {
  261.             *gap++ = ch == '\r' ? '\n' : ch;
  262.         }
  263.         index = pos(egap);
  264.         display();
  265.     }
  266. }
  267.  
  268. void
  269. delete()
  270. {
  271.     movegap();
  272.     if (egap < ebuf)
  273.         index = pos(++egap);
  274. }
  275.  
  276. void
  277. file()
  278. {
  279.     int i;
  280.     int j = index;
  281.     index = 0;
  282.     movegap();
  283.     write(i = creat(filename, MODE), egap, (int)(ebuf-egap));
  284.     close(i);
  285.     index = j;
  286. }
  287.  
  288. void
  289. display()
  290. {
  291.     char *p;
  292.     int i, j;
  293.     if (index < page)
  294.         page = prevline(index);
  295.     if (epage <= index) {
  296.         page = nextline(index); 
  297.         i = page == pos(ebuf) ? LINES-2 : LINES; 
  298.         while (0 < i--)
  299.             page = prevline(page-1);
  300.     }
  301.     move(0, 0);
  302.     i = j = 0;
  303.     epage = page;
  304.     while (1) {
  305.         if (index == epage) {
  306.             row = i;
  307.             col = j;
  308.         }
  309.         p = ptr(epage);
  310.         if (LINES <= i || ebuf <= p)
  311.             break;
  312.         if (*p != '\r') {
  313.             addch(*p);
  314.             j += *p == '\t' ? 8-(j&7) : 1;
  315.         }
  316.         if (*p == '\n' || COLS <= j) {
  317.             ++i;
  318.             j = 0;
  319.         }
  320.         ++epage;
  321.     }
  322.     clrtobot();
  323.     if (++i < LINES)
  324.         mvaddstr(i, 0, "<< EOF >>");
  325.     move(row, col);
  326.     refresh();
  327. }
  328.  
  329. int
  330. main(argc, argv)
  331. int argc;
  332. char **argv;
  333. {
  334.     int ch, i;
  335.     egap = ebuf = buf + BUF;
  336.     if (argc < 2)
  337.         return (2);
  338.     initscr();
  339.     raw();
  340.     noecho();
  341.     idlok(stdscr, 1);
  342.     if (0 < (i = open(filename = *++argv, 0))) {
  343.         gap += read(i, buf, BUF);
  344.         if (gap < buf)
  345.             gap = buf;
  346.         close(i);
  347.     }
  348.     top();
  349.     while (!done) {
  350.         display();
  351.         i = 0; 
  352.         ch = getch(); 
  353.         while (key[i] != '\0' && ch != key[i])
  354.             ++i;
  355.         (*func[i])();
  356.     }
  357.     endwin();
  358.     return (0);
  359. }
  360.